1 module unde.games.dizzy.omega.grasshopper;
2 
3 import derelict.opengl3.gl;
4 
5 import std.conv;
6 import std.math;
7 import std.algorithm;
8 import std.stdio;
9 import unde.games.object;
10 import unde.games.renderer;
11 import unde.games.collision_detector;
12 import unde.games.object;
13 import unde.global_state;
14 
15 class Grasshopper:StaticGameObject
16 {
17     static int num;
18     int number;
19 
20     bool killed;
21     bool sprayed;
22     
23     enum SPEED = 0.1;
24     enum G = 0.01;
25     enum MAX_V = 0.1;
26     enum JUMP_V = 0.25;
27 
28     float def_x, def_y, def_z;
29     int dir = 1;
30     float dx = 0.0, dy = 0.0;
31     long frame;
32     long start_jump_frame;
33     long end_jump_frame;
34     long stopped_frame = 1;
35 
36     bool solid;
37 
38     LiveGameObject the_hero;
39 
40     string grasshopper_solid, grasshopper_solid1;
41 
42     this(MainGameObject root, float[3] coords, string grasshopper_solid,
43         string grasshopper_solid1, LiveGameObject the_hero)
44     {
45         def_x = x = coords[0];
46         def_y = y = coords[1];
47         def_z = z = coords[2];
48         number = num++;
49         for (int i=0; i < 6; i++)
50         {
51             models["grasshopper-"~i.to!(string)] = root.models["grasshopper-"~i.to!(string)];
52         }
53         collision_objects["solid"] = root.collision_objects[grasshopper_solid];
54 
55         this.grasshopper_solid = grasshopper_solid;
56         this.grasshopper_solid1 = grasshopper_solid1;
57         
58         this.the_hero = the_hero;
59         super(root);
60     }
61 
62     void change_solid(bool i)
63     {
64         solid = i;
65         if (i) collision_objects["solid"] = root.collision_objects[grasshopper_solid1];
66         else collision_objects["solid"] = root.collision_objects[grasshopper_solid];
67     }
68 
69     void kill()
70     {
71         killed = true;
72     }
73 
74     void spray()
75     {
76         sprayed = true;
77     }
78 
79     override void draw(GlobalState gs)
80     {
81         if (killed) return;
82         
83         glPushMatrix();
84         glTranslatef(x, y, z);
85         if (dir < 0) glRotatef(180,0,1,0);
86         long fr;
87         if (start_jump_frame > 0)
88             fr = (cast(long)min((frame - start_jump_frame)/2, 5));
89         if (end_jump_frame > 0)
90             fr = (cast(long)max(5 - (frame - end_jump_frame)/2, 0));
91         //writefln("grasshopper (%s, %s, %s)", x, y, z);
92         recursive_render(gs, models["grasshopper-"~fr.to!(string)]);
93         glPopMatrix();
94     }
95 
96     immutable float side_sensor_dx = 1.0;
97     immutable float[2] side_sensor_y = [0.5, 0.8];
98     
99     immutable float bottom_sensor_dx = 0.6;
100     immutable float bottom_sensor_dy = 0.5;
101 
102     immutable float jump_sensor_dx = 0.6;
103     immutable float jump_sensor_dy = 1.0;
104 
105     override bool tick(GlobalState gs)
106     {
107         if (killed) return true;
108         
109         frame++;
110         x += dx;
111         y += dy;
112 
113         if (collision_objects["solid"] is null) return true;
114 
115         if (the_hero is null)
116         {
117             if (if_intersect (collision_objects["solid"], [x, y+side_sensor_y[0], z-5*side_sensor_dx, x+side_sensor_dx, y+side_sensor_y[1], z+5*side_sensor_dx]) > 0 ||
118                 (the_hero !is null && the_hero.x - 1.5 < x+side_sensor_dx && x+side_sensor_dx < the_hero.x + 1.5 &&
119                     the_hero.y < y && y < the_hero.y + 2.5))
120             {
121                 dx = SPEED/10;
122                 dir = 1;
123             }
124         }
125         else
126         {
127             if (dx < 0 && (if_intersect (collision_objects["solid"], [x-side_sensor_dx, y+side_sensor_y[0], z-side_sensor_dx, x, y+side_sensor_y[1], z+side_sensor_dx]) > 0 ||
128                 (the_hero !is null && the_hero.x - 1.5 < x-side_sensor_dx && x-side_sensor_dx < the_hero.x + 1.5 &&
129                     the_hero.y < y && y < the_hero.y + 2.5)))
130             {
131                 dx = SPEED;
132                 dir = 1;
133             }
134             else if (dx > 0 && (if_intersect (collision_objects["solid"], [x, y+side_sensor_y[0], z-side_sensor_dx, x+side_sensor_dx, y+side_sensor_y[1], z+side_sensor_dx]) > 0 ||
135                 (the_hero !is null && the_hero.x - 1.5 < x+side_sensor_dx && x+side_sensor_dx < the_hero.x + 1.5 &&
136                     the_hero.y < y && y < the_hero.y + 2.5)))
137             {
138                 dx = -SPEED;
139                 dir = -1;
140             }
141         }
142 
143         Intersect on_the_ground =
144             if_intersect (collision_objects["solid"], [x-bottom_sensor_dx, y, z-5*bottom_sensor_dx, x+bottom_sensor_dx, y+bottom_sensor_dy, z+5*bottom_sensor_dx]);
145 
146         Intersect ground_soon =
147             if_intersect (collision_objects["solid"], [x-jump_sensor_dx, y-jump_sensor_dy, z-5*jump_sensor_dx, x+jump_sensor_dx, y, z+5*jump_sensor_dx]);
148 
149         if (stopped_frame == 0 && dy > -MAX_V)
150         {
151             dy -= G;
152         }
153 
154         if (stopped_frame > 0 && frame - stopped_frame > 150)
155         {
156             stopped_frame = 0;
157             start_jump_frame = frame;
158             dx = SPEED * dir;
159             dy = JUMP_V;
160         }
161         
162         if (start_jump_frame > 0 && dy < 0 && ground_soon > 0)
163         {
164             start_jump_frame = 0;
165             end_jump_frame = frame;
166         }
167 
168         if (end_jump_frame > 0 && on_the_ground > 0)
169         {
170             dx = 0;
171             dy = 0;
172             end_jump_frame = 0;
173             stopped_frame = frame;
174         }
175         
176         return true;
177     }    
178 
179     override void load(string[string] s)
180     {
181         string p = "grasshopper"~number.to!(string);
182         if (p~"-x" in s)
183             x = s[p~"-x"].to!(float);
184         else
185             x = def_x;
186             
187         if (p~"-y" in s)
188             y = s[p~"-y"].to!(float);
189         else
190             y = def_y;
191             
192         if (p~"-z" in s)
193             z = s[p~"-z"].to!(float);
194         else
195             z = def_z;
196 
197         if (p~"-dx" in s)
198             dx = s[p~"-dx"].to!(float);
199         else
200             dx = 0.0;
201 
202         if (dx < 0) dir = -1;
203         else if (dx > 0) dir = 1;
204 
205         if (p~"-dy" in s)
206             dy = s[p~"-dy"].to!(float);
207         else
208             dy = 0.0;
209 
210         if (p~"-frame" in s)
211             frame = s[p~"-frame"].to!(long);
212         else
213             frame = 0;
214 
215         if (p~"-start_jump_frame" in s)
216             start_jump_frame = s[p~"-start_jump_frame"].to!(long);
217         else
218             start_jump_frame = 0;
219 
220         if (p~"-end_jump_frame" in s)
221             end_jump_frame = s[p~"-end_jump_frame"].to!(long);
222         else
223             end_jump_frame = 0;
224 
225         if (p~"-stopped_frame" in s)
226             stopped_frame = s[p~"-stopped_frame"].to!(long);
227         else
228             stopped_frame = 1;
229 
230         if (p~"-solid" in s)
231             solid = (s[p~"-solid"] == "pit");
232         else
233             solid = false;
234 
235         change_solid(solid);
236 
237         if (p in s)
238         {
239             killed = (s[p] == "killed");
240         }
241         else
242             killed = false;
243 
244         if (p~"-s" in s)
245         {
246             sprayed = (s[p~"-s"] == "sprayed");
247         }
248         else
249             sprayed = false;
250     }
251 
252     override void save(ref string[string] s)
253     {
254         string p = "grasshopper"~number.to!(string);
255         if (killed)
256             s[p] = "killed";
257 
258         if (sprayed)
259             s[p~"-s"] = "sprayed";
260 
261         s[p~"-x"] = x.to!(string);
262         s[p~"-y"] = y.to!(string);
263         s[p~"-z"] = z.to!(string);
264         s[p~"-dx"] = dx.to!(string);
265         s[p~"-dy"] = dy.to!(string);
266         s[p~"-frame"] = frame.to!(string);
267         s[p~"-start_jump_frame"] = start_jump_frame.to!(string);
268         s[p~"-end_jump_frame"] = end_jump_frame.to!(string);
269         s[p~"-stopped_frame"] = stopped_frame.to!(string);
270         if (solid)
271             s[p~"-solid"] = "pit";
272     }    
273 }